ipblock design in GEZEL

48
ipblock design in GEZEL Patrick Schaumont Virginia Tech Dept. of Electrical and Computer Engineering September 2010

description

ipblock design in GEZEL. Patrick Schaumont Virginia Tech Dept. of Electrical and Computer Engineering September 2010. What are ipblock?. An ipblock is a black-box simulation entity for GEZEL. Name. Interface. ipblock M(in address : ns(5); in wr,rd   : ns(1); - PowerPoint PPT Presentation

Transcript of ipblock design in GEZEL

Page 1: ipblock design in GEZEL

ipblock design in GEZEL

Patrick Schaumont

Virginia TechDept. of Electrical and Computer Engineering

September 2010

Page 2: ipblock design in GEZEL

2

What are ipblock?

• An ipblock is a black-box simulation entity for GEZEL

ipblock M(in address : ns(5); in wr,rd   : ns(1); in idata   : ns(8); out odata   : ns(8)) { iptype "ram"; ipparm "wl=8"; ipparm "size=32"; }

InterfaceName

Type

Parameters

Page 3: ipblock design in GEZEL

3

Applications of ipblock

• Capture functionality not available as FSMD• FSMD does not exist: memory modules• FSMD unavailable: IP, complex modules, ..

• Interfaces to other simulation engines• Instruction-set simulators: ARM, 8051• Other languages/environments: SystemC,...

• Extensions of GEZEL simulation capabilities• Collect signal statistics• Debug facility

Page 4: ipblock design in GEZEL

4

Who develops ipblock?

GEZEL Designers GEZEL Users

ipblock

with generic use design-specific

Page 5: ipblock design in GEZEL

5

How are ipblock implemented?

aipblock

ipblock

GEZEL class lib(data types,

symbol table, ...)C++

ld.sofdlsim/gplatform

dynamic-link librarystatically linked

EXE

Page 6: ipblock design in GEZEL

6

Operational Principle

• ipblock are cycle-based simulation models• A cycle-based simulation has two phases

per cycle: evaluate and (state) update

R1 R2 R3logic L1 logic L2

Page 7: ipblock design in GEZEL

7

Operational Principle

• ipblock are cycle-based simulation models• A cycle-based simulation has two phases

per cycle: evaluate and (state) update

R1

R2

R3

logic L1

logic L2

R1

R2

R3

Cycle N Cycle N + 1

Evaluate: next_R1 = ... next_R2 = Logic_L1(R1); next_R3 = Logic_L2(R2);

Update: R1 = next_R1; R2 = next_R2; R3 = next_R3;

Page 8: ipblock design in GEZEL

8

Operational Principle

• ipblock are cycle-based simulation models• A cycle-based simulation has two phases

per cycle: evaluate and (state) update• Evaluate and update can be called only once

per cycle

R1 R3logic L1 logic L2

GEZEL ensures that all Evaluate( ) are properly sorted:Logic_L1(R1) will be called BEFORE Logic L2(L1_output)

Page 9: ipblock design in GEZEL

9

Operational Principle

• ipblock are cycle-based simulation models• A cycle-based simulation has two phases

per cycle: evaluate and (state) update• Evaluate and update are called only once

per cycle

logic L1 logic L1 logic L2

If the execution order for Evaluate( ) cannot be determined,the simulator terminates ('combinatorial loop')

Page 10: ipblock design in GEZEL

10

Combinational ipblock

• By default, have a single evaluate function, called once per clock cycle

ipblock

ipblockipblock

fsmd

OK

Not OK

Page 11: ipblock design in GEZEL

11

Simple ipblock: combinational

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock";}

GEZEL

C++

void myblock::run() { ioval[2]->assignulong(ioval[0]->toulong() + ioval[1]->toulong());}

class myblock : public aipblock { public: void run();};

+

Page 12: ipblock design in GEZEL

12

Simple ipblock: combinational

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock";}

GEZEL

C++

void myblock::run() { ioval[2]->assignulong(ioval[0]->toulong() + ioval[1]->toulong());}

class myblock : public aipblock { public: void run();};

ioval[0]

ioval[1]

ioval[2]

a

b

c

Page 13: ipblock design in GEZEL

13

Simple ipblock: combinational

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock";}

GEZEL

C++

void myblock::run() { ioval[2]->assignulong(ioval[0]->toulong() + ioval[1]->toulong());}

class myblock : public aipblock { public: void run();};

• run() is called once per clock cycle• When called, input ioval[ ] reflects proper value

for that clock cycle• When called, output ioval[ ] must be assigned

proper value for that clock cycle

Page 14: ipblock design in GEZEL

14

Adding parameters

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock"; ipparm "thisparam=thatval";}

GEZEL

C++

void myblock::run() { ioval[2]->assignulong(ioval[0]->toulong() + ioval[1]->toulong());}

void myblock::setparam(char *n) { // ...}

class myblock : public aipblock { public: void run(); void setparam(char *);};

call constructor

for each 'ipparm'call setparam

for each cyclecall run

Page 15: ipblock design in GEZEL

15

Terminal-check function

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock"; ipparm "thisparam=thatval";}

GEZEL

C++

class myblock : public aipblock { public: void run(); void setparam(char *); bool checkterminal(int n, char *tname, iodir d);};

bool myblock::checkterminal(int n, char *tname, iodir d) { switch(n) { case 0 : return (isinput(d) && isname(tname, "a")); break; ... } return false;}

• ipblock use positional port matching• checkterminal verifies that ioval[0] is

an input name "a", ioval[1] is input "b", ...

Page 16: ipblock design in GEZEL

16

Terminal-check function

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock"; ipparm "thisparam=thatval";}

GEZEL

C++

class myblock : public aipblock { public: void run(); void setparam(char *); void checkterminal(..);};

call constructor

for each 'ipparm'call setparam

for each cyclecall run

for each i/o portcall checkterminal

Page 17: ipblock design in GEZEL

17

Completing the C++

#ifndef myblock_h#define myblock_h

#include "ipblock.h"

extern "C" aipblock *create_myblock(char *instname);

class myblock : public aipblock {

public: myblock(char *name); void setparm(char *); void run(); bool checkterminal(int n, char *tname, aipblock::iodir d); bool cannotSleepTest(); bool needsWakeupTest();};

#endif

myblock.h

Access to GEZEL library functions(aipblock definition, arbitrary-precision data types, ..)

Called by the dynamic-link facility,Function name depends on class name!

simulator control(see part 2)

Page 18: ipblock design in GEZEL

18

Completing the C++

myblock.cxx

#include "myblock.h"

extern "C" aipblock *create_myblock(char *instname) { return new myblock(instname);}

myblock::myblock(char *name) : aipblock(name) {..}

void myblock::setparm(char *_name) {..}

void myblock::run() {..}bool myblock::checkterminal(..) {..}

bool myblock::cannotSleepTest(){ return false;}

bool myblock::needsWakeupTest(){ return true;}

Default implementationfor combinational modules

Called by dynamic-link facility

Page 19: ipblock design in GEZEL

19

Compilation-Simulation Example

g++ -fPIC -O3 -I/opt/gezel-2.2/include/gezel -c myblock.cxx

g++ -shared -O3 \ -Wl,--rpath -Wl,/home/schaum/gezel/devel/build/lib \ myblock.o \ /opt/gezel-2.2/lib/libipconfig.so \ /opt/gezel-2.2/lib/libfdl.so \ -lgmp -ldl -o libmyblock.so

Compile:

Create dynamic-link library

Page 20: ipblock design in GEZEL

20

Compilation-Simulation Example

g++ -fPIC -O3 -I/opt/gezel-2.2/include/gezel -c myblock.cxx

g++ -shared -O3 \ -Wl,--rpath -Wl,/home/schaum/gezel/devel/build/lib \ myblock.o \ /opt/gezel-2.2/lib/libipconfig.so \ /opt/gezel-2.2/lib/libfdl.so \ -lgmp -ldl -o libmyblock.so

Compile:

Create dynamic-link library

position-independent code

.so library

path to gezel lib

gezel lib and predefined ipblocks

arbitrary precisionmath lib

dynamic link lib

Page 21: ipblock design in GEZEL

21

GEZEL File

ipblock ablock(in a, b : ns(8); out c : ns(8)) { iptype "myblock"; ipparm "thisparam=thatval";}

dp top { sig a, b, c : ns(8); reg a1 : ns(8); use ablock(a, b, c); always { a = a1; b = 2; $display("a ", a, " b ", b, " c ",c); a1 = a1 + 1; }}

system S { top;}

Page 22: ipblock design in GEZEL

22

Simulation

> /opt/gezel-2.2/bin/fdlsim ipb.fdl 5

set parm: thisparam=thatvala 0 b 2 c 2a 1 b 2 c 3a 2 b 2 c 4a 3 b 2 c 5a 4 b 2 c 6

1. parse ipb.fdl2. instantiate ipblock 2.1. link dynamic-link lib3. simulate 5 cycles

output:

define all FSM next-state

evaluate output of each dp

call ipblock with no output

update dp registers

Per clock cycle:

Page 23: ipblock design in GEZEL

23

Summary

#ifndef myblock_h#define myblock_h

#include "ipblock.h"

class myblock : public aipblock {

public: myblock(char *name); void setparm(char *); void run(); bool checkterminal(int n, char *tname, aipblock::iodir d); bool cannotSleepTest(); bool needsWakeupTest();};

#endif

Page 24: ipblock design in GEZEL

24

Sleep Cycle Mechanism

#ifndef myblock_h#define myblock_h

#include "ipblock.h"

class myblock : public aipblock {

public: myblock(char *name); void setparm(char *); void run(); bool checkterminal(int n, char *tname, aipblock::iodir d); bool cannotSleepTest(); bool needsWakeupTest();};

#endif

Page 25: ipblock design in GEZEL

25

Sleep Cycle Mechanism

Software(typ 1Mc/s)

Hardware(typ 10K/s)

100K cycles

100 cycles

100 cycles

100K cycles

100K cycles

Page 26: ipblock design in GEZEL

26

Sleep Cycle Mechanism

Software(typ 1Mc/s)

Hardware(typ 10K/s)

100K cycles

100 cycles

100 cycles

100K cycles

100K cycles

Without sleep-cycle:300,200 cycles @ 10K/s

=30.02 seconds

Page 27: ipblock design in GEZEL

27

Sleep Cycle Mechanism

Software(typ 1Mc/s)

Hardware(typ 10K/s)

100K cycles

100 cycles

100 cycles

100K cycles

100K cycles

With sleep-cycle:300K cycles @ 1M/s +

300K cycles (testing_overhead) +200 cycles @ 10K/s

=less than 0.5 seconds!

Page 28: ipblock design in GEZEL

28

Sleep Cycle Mechanism

• GEZEL simulator has two states:• Active:

– each clock cycle, evaluate all datapath outputs (and dependent signals), evaluate all registers, evaluate all ipblock

– perform sleep test

• Passive:– perform wakeup test

Page 29: ipblock design in GEZEL

29

Sleep Cycle Mechanism

• Transition from active to passive

Active

Passive

sleep_test = false

sleep_test = truewakeup_test = true

wakeup_test = false

Page 30: ipblock design in GEZEL

30

Sleep Test

• Sleep test evaluates to false in cycle X if:• Any register changes state during a clock X• Any FSM changes state during clock cycle X• Any ipblock returns true in

aipblock::cannotSleepTest()

• GEZEL simulator will call cannotSleepTest () once per cycle in active mode, default value should be false

• (why is my GEZEL cosimulation so slow?Might be because there is remaining HW activity in idle phases)

Page 31: ipblock design in GEZEL

31

Wakeup Test

• Wakeup test evaluates to true in cycle X if:• Any ipblock returns true in

aipblock::needsWakeupTest()

• GEZEL simulator will call needsWakeupTest () once per cycle in passive mode, default value should be false

• If needsWakeupTest() never returns false, your simulation will never sleep (may be the cause of a slow cosimulation)

• If needsWakeupTest() never returns true, your simulation will never wakeup (may be the cause of a ‘halted’ cosimulation)

Page 32: ipblock design in GEZEL

32

Example: 8051 cosimulation interface

8051 4 bi-directional ports

Three GEZEL ipblock:

ipblock my8051 { iptype "i8051system"; ipparm "exec=driver.ihx"; ipparm "verbose=1"; ipparm "period=1";}

ipblock my8051_datain(out data : ns(8)) { iptype "i8051systemsource"; ipparm "core=my8051"; ipparm "port=P1";}

ipblock my8051_dataout(in data : ns(8)) { iptype "i8051systemsink"; ipparm "core=my8051"; ipparm "port=P2";}

Core

Input port

Output port

Page 33: ipblock design in GEZEL

33

The Core

void i8051system::run() { if (sim.IsRunning()) { period_cnt--; if (period_cnt == 0) { period_cnt = period; sim.ClockTick(); if (! sim.IsRunning())

glbRunningISS--; } }}

bool i8051system::cannotSleepTest() { return false; // the ISS will continue to run in sleep mode // so we can also return 'OK to sleep'}

bool i8051system::needsWakeupTest() { run(); return false;}

Page 34: ipblock design in GEZEL

34

The Input Port

void i8051systemsink::run() { if (hook) { hook->writeRAM(address, ioval[0]->toulong()); }}

bool i8051systemsink::cannotSleepTest() { return false;}

(If you do not specify needsWakeupTest(), default implementation is used, which returns false)

Page 35: ipblock design in GEZEL

35

The Output Port

void i8051systemsource::run() {}

Obviously, it is the 8051 simulator that decides what the value of the output port should be. The 8051 simulator calls a functionexternalwrite(address, data) each time is performs a port write

Page 36: ipblock design in GEZEL

36

The Output Port

void i8051systemsource::run() {}

Obviously, it is the 8051 simulator that decides what the value of the output port should be. The 8051 simulator calls a functionexternalwrite(address, data) each time is performs a port write

void i8051externalwrite(int dev, unsigned char d) { i8051devmap[dev]->ioval[0]->assignulong((long) d); i8051devmap[dev]->touch();}

I8051devmap is an array of output port ipblocks that are

implemented by GEZEL

The result of the externalwrite( ) is that an ipblock output is updated

Page 37: ipblock design in GEZEL

37

The Output Port

void i8051systemsource::run() {}

bool i8051systemsource::needsWakeupTest() { bool v = interfacewritten; interfacewritten = false; return v;}

bool i8051systemsource::cannotSleepTest() { bool v = interfacewritten; interfacewritten = false; return v;}

void i8051systemsource::touch() { interfacewritten = true;}

void i8051externalwrite(int dev, unsigned char d) { i8051devmap[dev]->ioval[0]->assignulong((long) d); i8051devmap[dev]->touch();}

As a result ofthe 8051 WRITING

to the hardware,the cycle-simulation

will wake-up

Page 38: ipblock design in GEZEL

38

Review: One C++ class

#ifndef myblock_h#define myblock_h

#include "ipblock.h"

class myblock : public aipblock {

public: myblock(char *name); void setparm(char *); void run(); bool checkterminal(int n, char *tname, aipblock::iodir d); bool cannotSleepTest(); bool needsWakeupTest();};

#endif

OK!

Page 39: ipblock design in GEZEL

39

Ipblock are combinational

• By default, have a single evaluate function, run( ), called once per clock cycle

ipblock

ipblockipblock

fsmd

OK

Not OK

Page 40: ipblock design in GEZEL

40

Support for sequential IP block

• Define sequential IP block:

a sequential ipblock is an ipblock with an output which is is known and stable at the start of a clock cycle.

• Thus, ‘sequential’ is a property of an output, not an entire ipblock

Page 41: ipblock design in GEZEL

41

Support for Sequential IPblock

• For example, assume you develop a C++ class for this structure:

ipblock

CombFunction

Sequential output

Combinational output

Page 42: ipblock design in GEZEL

42

Support for Sequential IP block

• This will simulate fine !

ipblock

CombFunction

CombFunction

0

Page 43: ipblock design in GEZEL

43

Sequential IP Block in C++

#ifndef myblock_h#define myblock_h

#include "ipblock.h"

class myblock : public aipblock {

public: myblock(char *name); void setparm(char *); void run(); bool checkterminal(int n, char *tname, aipblock::iodir d); bool cannotSleepTest(); bool needsWakeupTest(); void regOutput(); void out_run();};

#endif

Page 44: ipblock design in GEZEL

44

regOutput

• Used in constructor to define an ipblock output as sequential

armsfu2x1::armsfu2x1(char *name) : aipblock(name) { deviceid = 0; hook = 0; myarm = 0; interfacewritten = false; regOutput(0); // d1 and d2 are registered regOutput(1);}

// ipblock mysfu(out d1 : ns(32); out d2 : ns(32);// in q1 : ns(32); in q2 : ns(32)) {// iptype "armsfu2x2";// ipparm "core = mycore"; -- core to hook into// ipparm "device = 0"; -- 2 possible devices per sfu type// }

Page 45: ipblock design in GEZEL

45

regOutput

• Used in constructor to define an ipblock output as sequential

// ipblock mysfu(out d1 : ns(32); out d2 : ns(32);// in q1 : ns(32); in q2 : ns(32)) {// iptype "armsfu2x2";// ipparm "core = mycore"; -- core to hook into// ipparm "device = 0"; -- 2 possible devices per sfu type// }

armsfu2x2Custom

Datapath(combinational)

d1d2

q1q2

OK!

Stable at the start of a clock cycle

Page 46: ipblock design in GEZEL

46

out_run( )

• out_run( ) is called at the start of the clock cycle, before any other run( ) is called, and before any signal or register is evaluated.

• Typically, out_run( ) is used to initialize regOutput outputs to a stable value for that clock cycle.

Page 47: ipblock design in GEZEL

47

Example: accumulator ipblock

ipblock

add

ipblock acc(in d : ns(8); out q : ns(8)) { iptype “accumulator”;}

myacc::myacc(char *name) : aipblock(name) { regOutput(0); accvalue = 0;}

myacc::out_run() { ioval[0]->assignulong(accvalue);}

myacc::run() { accvalue = accvalue + ioval[1]->toulong();}

Page 48: ipblock design in GEZEL

48

Final hints

• ipblock are a powerful extension mechanism for GEZEL• Puts a designer in control of design

environment• Allows to put hardware design in context

• Other neat tool: icg (incremental code generator)• Generates ipblock C++ out of GEZEL code• Useful to speed up simulation (3X – 10X faster)• Useful to compile HW to SW

nice open research problems left here