Exemple #1
0
async def unary(din: Uint['w_data']) -> Uint['2**(int(w_data)-1)']:
    '''Returns the unary representation of a binary number'''
    async with din as val:
        if val > 2**(din.dtype.width - 1):
            sim_log().error(
                f'{val} supplied, but only numbers <= {2**(din.dtype.width-1)} supported for this instance'
            )

        if val == 0:
            yield 0
        else:
            yield int('1' * int(val), 2)
Exemple #2
0
 def read(self):
     self.active = self.c_get_api(self.dout)
     # print(
     #     f'{self.port.basename}: {self.active}, {self.from_c_data(self.dout)}'
     # )
     if self.active:
         try:
             return self.port.dtype.decode(self.from_c_data(self.dout))
         except ValueError as e:
             sim_log().error(
                 str(e) + f'\n    - received at port "{self.port.name}"')
     else:
         raise CosimNoData
Exemple #3
0
    def before_run(self, sim):
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

        if self.run_cosim:
            import uuid
            filename = str(uuid.uuid4())
        else:
            filename = "svsock.s"

        self.port = os.path.join(tempfile.gettempdir(), filename)

        if os.path.exists(self.port):
            os.remove(self.port)
        self.sock.bind(self.port)

        # Listen for incoming connections
        # self.sock.listen(len(self.gear.in_ports) + len(self.gear.out_ports))
        self.sock.listen(1)

        self.build()

        # if self.rebuild:
        #     self.build()
        # else:
        #     self.kwds['nobuild'] = True

        if not self.run_cosim:
            self.invoke_cosim()
            self.conn, addr = self.sock.accept()
        else:
            self.sock.settimeout(5)

            self.cosim_pid = self.invoke_cosim()

            ret = None
            while ret is None:
                try:
                    self.conn, addr = self.sock.accept()
                    break
                except socket.timeout:
                    ret = self.cosim_pid.poll()
                    if ret is not None:
                        sim_log().error(
                            f'Cosimulator error: {ret}. Check log File "{self.outdir}/log.log"'
                        )
                        raise CosimulatorStartError

        msg = self.conn.recv(1024)
        port_name = msg.decode()

        sim_log().debug(f"Connection received for {port_name}")
Exemple #4
0
def typeseq(t, v):
    if type(v) == t:
        yield v
    else:
        try:
            for d in TypeDrvVisitor().visit(v, t):
                try:
                    yield t(d)
                except (TypeError, ValueError):
                    sim_log().error(
                        f'Cannot convert value "{d}" to type "{repr(t)}"')
        except (TypeError, ValueError):
            sim_log().error(
                f'Cannot convert sequence "{v}" to the "{repr(t)}"')
Exemple #5
0
def find_target_cons(intf):
    # Who is consumer port? Case when not broadcast!
    # cons_rtl_port = intf.consumers[0]
    end_c = get_end_consumer(intf)
    if len(end_c) != 1:
        if len(end_c) > 1:
            sim_log().debug(f'Find target cons: found broadcast')
        return None
    cons_rtl_port = end_c[0]
    cons_rtl_node, port_id = cons_rtl_port.node, cons_rtl_port.index
    cons_gear = cons_rtl_node.gear
    cons_port = cons_gear.in_ports[port_id]

    return cons_port
Exemple #6
0
    def get_rand(self, name):
        ret = os.system(
            f"cd {self.outdir}; g++ -fpic -shared -I. -I$SYSTEMC_INCLUDE -I$SCV_INCLUDE -Wall -Wformat -O2 $SCV_LIBDIR/libscv.so -L$SYSTEMC_LIBRID $SYSTEMC_LIBDIR/libsystemc.so -lpthread -pthread -Wl,-rpath -Wl,$SCV_LIBDIR -Wl,-rpath -Wl,$SYSTEMC_LIBDIR -o {name} {name}.cpp"
        )

        if ret != 0:
            sim_log().warning(
                'Possible reason for exception: Queues not supported in SCV')
            raise SCVCompileError(
                f'Constrained random library compilation failed for module {name}.'
            )

        scvlib = ctypes.CDLL(os.path.join(self.outdir, name))
        t = self.get_dtype_by_name(name)
        return SCVTypeSeqVisitor(scvlib).visit(t, name)
Exemple #7
0
async def scoreboard(*din: b't', report=None, cmp=None) -> None:
    """Generic scoreboard used from comparing actual results from the DUT to
    expected results. Eventual mismatches are asserted using the ``sim_assert``
    function meaning that any ``error`` behaviour is controled via the ``sim``
    logger ``error`` settings.

    Args:
        din: Outputs from both the DUT and ref. model. All intpus are a PyGears
          interface
        report: List to with comparison results are appended
        tolerance: Optional tolerance when comparing results. The DUT result must
          be in the (expected - tolerance, expected+tolerance) range

    Returns:
        None
    """
    def match_exact(x, y):
        return x == y

    if cmp is None:
        cmp = match_exact

    # print(f'Number of matches: -\r', end='')
    cnt = 0
    match_cnt = 0
    try:
        while True:
            items = []
            for d in din:
                items.append(await d.get())

            match = all(cmp(v, items[0]) for v in items)

            if report is not None:
                report.append({'match': match, 'items': items})

            cnt += 1
            if match:
                match_cnt += 1

            sim_assert(match, f'mismatch on #{cnt}: {items[0]}, {items[1]}')

            # print(f'Number of matches: {match_cnt:>4}/{cnt:>4}\r', end='')

    except GearDone as e:
        sim_log().info(f'Number of matches: {match_cnt:>4}/{cnt:>4}')
        raise e
Exemple #8
0
def find_target_prod(intf):
    # Who is producer gear?
    # prod_rtl_port = intf.producer
    end_p = get_producer(intf)
    if len(end_p) != 1:
        return None
    if isinstance(end_p[0], OutPort):
        prod_rtl_port = end_p[0]
        prod_rtl_node = prod_rtl_port.node
        prod_gear = prod_rtl_node.gear
    else:
        prod_gear = end_p[0].gear
    if len(prod_gear.child):
        if len(prod_gear.child) > 1:
            sim_log().warning(
                f'ActivityCosim: prod has more than one child. Setting on first.'
            )
        return prod_gear.child[0]
    else:
        return prod_gear
Exemple #9
0
    def finish(self):
        if self.sock:
            if self.conn:
                try:
                    self.send_cmd(CMD_FINISH)
                    time.sleep(0.5)
                except BrokenPipeError:
                    pass

            sim_log().info(f'Done. Closing the socket...')
            self.sock.close()
            time.sleep(1)

            if self.cosim_pid is not None:
                self.cosim_pid.terminate()

            self.sock = None
            self.cosim_pid = None
            self.conn = None
            atexit.unregister(self.finish)
Exemple #10
0
    def after_run(self, sim):
        for sim_gear in sim.sim_gears:
            module = sim_gear.gear

            if module.definition == decouple_din:
                if not module.queue.empty():
                    if 'data_in_decouple' in self.hooks:
                        self.hooks['data_in_decouple'](module)
                    sim_log().error(f'Data left in decouple: {module.name}')

            for p in module.in_ports:
                status = self.get_port_status(p)

                if status == "active":
                    src_port = get_source_producer(p, sim=True).consumers[0]

                    if src_port.gear.definition == const:
                        # Skip constants since they are never done
                        continue

                    if 'not_ack' in self.hooks:
                        self.hooks['not_ack'](module, p)
                    sim_log().error(
                        f'{src_port.gear.name}.{src_port.basename} -> {module.name}.{p.basename} was not acknowledged'
                    )

                if status == "waited":
                    src_port = self.blockers[p]
                    if 'waiting' in self.hooks:
                        self.hooks['waiting'](module, p)
                    sim_log().debug(
                        f'{p.gear.name}.{p.basename} waiting on {src_port.gear.name}.{src_port.basename}'
                    )
Exemple #11
0
    def __init__(self,
                 trace_fn='pygears.vcd',
                 include=Inject('debug/trace'),
                 tlm=False,
                 shmidcat=Inject('sim_extens/vcd/shmidcat'),
                 vcd_fifo=Inject('sim_extens/vcd/vcd_fifo'),
                 sim=Inject('sim/simulator'),
                 outdir=Inject('results-dir')):

        super().__init__()
        self.sim = sim
        self.finished = False
        self.vcd_fifo = vcd_fifo
        self.shmidcat = shmidcat
        self.outdir = outdir
        self.trace_fn = None
        self.shmid_proc = None

        vcd_visitor = VCDHierVisitor(include, tlm)
        vcd_visitor.visit(find('/'))

        if not vcd_visitor.vcd_vars:
            self.deactivate()
            return

        self.trace_fn = os.path.abspath(os.path.join(self.outdir, trace_fn))
        atexit.register(self.finish)

        try:
            subprocess.call(f"rm -f {self.trace_fn}", shell=True)
        except OSError:
            pass

        if self.vcd_fifo:
            subprocess.call(f"mkfifo {self.trace_fn}", shell=True)
        else:
            sim_log().info(f'Main VCD dump to "{self.trace_fn}"')

        if self.shmidcat:
            self.shmid_proc = subprocess.Popen(f'shmidcat {self.trace_fn}',
                                               shell=True,
                                               stdout=subprocess.PIPE)

            # Wait for shmidcat to actually open the pipe, which is necessary
            # to happen prior to init of the verilator. If shmidcat does not
            # open the pipe, verilator will get stuck
            import time
            time.sleep(0.1)

        self.vcd_file = open(self.trace_fn, 'w')

        if self.shmidcat:
            self.shmid = self.shmid_proc.stdout.readline().decode().strip()
            sim_log().info(f'Main VCD dump to shared memory at 0x{self.shmid}')

        self.writer = VCDWriter(self.vcd_file, timescale='1 ns', date='today')

        reg['VCDWriter'] = self.writer
        reg['VCD'] = self

        self.clk_var = self.writer.register_var('', 'clk', 'wire', size=1, init=1)

        self.timestep_var = self.writer.register_var('', 'timestep', 'integer', init=0)

        self.handhake = set()

        self.vcd_vars = {
            intf: register_traces_for_intf(intf.dtype, scope, self.writer)
            for intf, scope in vcd_visitor.vcd_vars.items()
        }

        for intf in self.vcd_vars:
            intf.events['put'].append(self.intf_put)
            intf.events['ack'].append(self.intf_ack)

        self.writer.flush()
Exemple #12
0
 def get_rand(self, name):
     sim_log().error('Get rand function not implemented.')
Exemple #13
0
 def create_type_cons(self, desc={}):
     sim_log().error('Create type constraints function not implemented.')
Exemple #14
0
 def after_call_forward(self, sim, sim_gear):
     sim_log().info(f'forward')
     return True
Exemple #15
0
 def after_call_back(self, sim, sim_gear):
     sim_log().info(f'back')
     return True
Exemple #16
0
async def register_file_write(request: TWriteRequest, *, storage):
    async with request as req:
        if req['addr'] != 0:
            sim_log().info(f'Writing {req["data"]} to x{int(req["addr"])}')
            storage[int(req['addr'])] = req['data']
Exemple #17
0
    def cosim_activity(self, g, top_name):
        outdir = reg['results-dir']
        activity_path = os.path.join(outdir, 'activity.log')

        if not os.path.isfile(activity_path):
            return

        with open(activity_path, 'r') as log:
            for line in log:
                activity_name = line.rpartition(': ')[0]
                activity_name = activity_name.replace('top.dut.',
                                                      f'{top_name}/')
                activity_name = activity_name.rpartition('.')[0]
                activity_name = activity_name.replace('_i.', '/')
                gear_name, _, intf_name = activity_name.rpartition('/')

                # Const always has valid high
                const_regex = r'.*_const(?P<num>\d+)_s'
                const_regex_one = r'.*_const_s'
                if not (re.match(const_regex, intf_name)
                        or re.match(const_regex_one, intf_name)):
                    sim_log().error(
                        f'Cosim spy not acknowledged: {activity_name}')

                if self.draw_graph:
                    bc_regex = r'.*_bc_(?P<num>\d+).*'
                    if re.match(bc_regex, intf_name):
                        sim_log().debug(
                            f'Activity monitor cosim: bc not supported {activity_name}'
                        )
                        continue

                    intf = find_target_intf(gear_name, intf_name)
                    if intf is None:
                        sim_log().error(
                            f'Cannot find matching interface for {activity_name}'
                        )
                        continue
                    if intf.is_broadcast:
                        sim_log().debug(
                            f'Intf bc not supported {activity_name}')
                        continue

                    try:
                        prod_gear = find_target_prod(intf)
                        set_blocking_node(g, prod_gear)
                    except (KeyError, AttributeError):
                        sim_log().debug(
                            f'Cannot find node for {activity_name}')

                    try:
                        cons_port = find_target_cons(intf)
                        set_blocking_edge(g, cons_port)
                    except (KeyError, AttributeError):
                        sim_log().debug(
                            f'Cannot find edge for {activity_name}')
Exemple #18
0
    def setup(self):
        # TODO: When reusing existing verilated build, add test to check
        # whether verilated module is the same as the current one (Maybe hash check?)
        if self.rebuild:
            sim_log().info(f'Verilating...')
            build(self.top, self.outdir, postsynth=False, lang=self.lang)
            sim_log().info(f'Done')

        file_struct = get_file_struct(self.top, self.outdir)

        tracing_enabled = bool(reg['debug/trace'])
        if tracing_enabled:
            sim_log().info(f"Debug: {reg['debug/trace']}")
            self.trace_fn = os.path.join(reg["results-dir"],
                                         f'{self.name}.vcd')
            try:
                subprocess.call(f"rm -f {self.trace_fn}", shell=True)
            except OSError:
                pass

            if self.vcd_fifo:
                subprocess.call(f"mkfifo {self.trace_fn}", shell=True)
            else:
                sim_log().info(f'Verilator VCD dump to "{self.trace_fn}"')
        else:
            self.trace_fn = ''

        try:
            self.verilib = ctypes.CDLL(file_struct['dll_path'])
        except OSError:
            raise VerilatorCompileError(
                f'Verilator compiled library for the gear "{self.gear.name}"'
                f' not found at: "{file_struct["dll_path"]}"')

        self.finished = False
        atexit.register(self._finish)

        if self.shmidcat and tracing_enabled:
            self.shmid_proc = subprocess.Popen(f'shmidcat {self.trace_fn}',
                                               shell=True,
                                               stdout=subprocess.PIPE)

            # Wait for shmidcat to actually open the pipe, which is necessary
            # to happen prior to init of the verilator. If shmidcat does not
            # open the pipe, verilator will get stuck
            import time
            time.sleep(0.1)

        self.verilib.init.argtypes = [ctypes.c_char_p]

        assert self.verilib.init(self.trace_fn.encode('utf8')) != 0

        if self.shmid_proc:
            self.shmid = self.shmid_proc.stdout.readline().decode().strip()
            sim_log().info(
                f'Verilator VCD dump to shared memory at 0x{self.shmid}')

        self.handlers = {}
        for cp in self.in_cosim_ports:
            self.handlers[cp.name] = CInputDrv(self.verilib, cp.port, cp.name)

        for cp in self.out_cosim_ports:
            self.handlers[cp.name] = COutputDrv(self.verilib, cp.port, cp.name)

        super().setup()