|
47 | 47 | from vsc.model.source_info import SourceInfo |
48 | 48 | from vsc.types import rangelist, bit_t, to_expr, type_base, enum_t, type_enum, \ |
49 | 49 | expr, field_info |
| 50 | +from vsc.impl.wildcard_bin_factory import WildcardBinFactory |
| 51 | +from vsc.model.coverpoint_bin_single_wildcard_model import CoverpointBinSingleWildcardModel |
| 52 | +from vsc.model.wildcard_binspec import WildcardBinspec |
50 | 53 |
|
51 | 54 |
|
52 | 55 | def covergroup(T): |
@@ -437,6 +440,138 @@ def build_cov_model(self, parent, name): |
437 | 440 |
|
438 | 441 | return ret |
439 | 442 |
|
| 443 | +class wildcard_bin(object): |
| 444 | + """Specifies a single wildcard coverage bin""" |
| 445 | + def __init__(self, *args): |
| 446 | + # Capture the declaration location of this bin |
| 447 | + self.srcinfo_decl = SourceInfo.mk() |
| 448 | + |
| 449 | + self.range_l = [] |
| 450 | + for a in args: |
| 451 | + if isinstance(a, tuple): |
| 452 | + # Expressed in mask form |
| 453 | + # (value, mask) where 1-bits in mask are compared and 0-bits are ignored |
| 454 | + self.range_l.append(a) |
| 455 | + elif isinstance(a, str): |
| 456 | + # Expressed in string form in either oct, hex, or bin format |
| 457 | + # |
| 458 | + value, mask = WildcardBinFactory.str2bin(a) |
| 459 | + self.range_l.append((value,mask)) |
| 460 | + else: |
| 461 | + raise Exception("Unknown argument %s to wildcard bin. Expect tuple or string" % ( |
| 462 | + str(a))) |
| 463 | + |
| 464 | + def build_cov_model(self, parent, name): |
| 465 | + ret = CoverpointBinSingleWildcardModel( |
| 466 | + name, |
| 467 | + WildcardBinspec(self.range_l)) |
| 468 | + ret.srcinfo_decl = self.srcinfo_decl |
| 469 | + |
| 470 | + return ret |
| 471 | + |
| 472 | +class wildcard_bin_array(object): |
| 473 | + """Specifies an array of bins using wildcard specifications""" |
| 474 | + |
| 475 | + def __init__(self, nbins, *args): |
| 476 | + """ |
| 477 | + args may be one of two formats |
| 478 | + - Single list of wildcard strings (eg "0x82x") |
| 479 | + - Single list of value/mask tuples (eg [(0x820,0xFF0)]) |
| 480 | + - Single string |
| 481 | + - Single tuple |
| 482 | + """ |
| 483 | + self.nbins = nbins |
| 484 | + self.range_l = [] |
| 485 | + |
| 486 | + # Convert the specification into canonical form: list of tuples |
| 487 | + if len(args) == 1: |
| 488 | + if isinstance(args[0], str): |
| 489 | + value, mask = WildcardBinFactory.str2bin(args[0]) |
| 490 | + self.range_l.extend(WildcardBinFactory.valmask2binlist(value, mask)) |
| 491 | + elif isinstance(args[0], (list,tuple)): |
| 492 | + # value/mask |
| 493 | + if len(args[0]) != 2: |
| 494 | + raise Exception("Wildcard bin specification requires two elements (value,mask)") |
| 495 | + |
| 496 | + self.range_l.extend(WildcardBinFactory.valmask2binlist(args[0][0], args[0][1])) |
| 497 | + else: |
| 498 | + raise Exception("Bin specification " + str(args[0]) + " is neither string nor value/mask") |
| 499 | + pass |
| 500 | + else: |
| 501 | + # Multiple arguments. Expect each to be a single-level string or tuple |
| 502 | + for a in args: |
| 503 | + if isinstance(a,(list,tuple)): |
| 504 | + if len(a) != 2: |
| 505 | + raise Exception("Wildcard bin range " + str(a) + " must have two elements") |
| 506 | + else: |
| 507 | + self.range_l.extend(WildcardBinFactory.valmask2binlist(a[0], a[1])) |
| 508 | + elif isinstance(a,str): |
| 509 | + value, mask = WildcardBinFactory.str2bin(a) |
| 510 | + self.range_l.extend(WildcardBinFactory.valmask2binlist(value, mask)) |
| 511 | + else: |
| 512 | + raise Exception("Wildcard bin specification " + str(a) + " is neither value nor range") |
| 513 | + |
| 514 | + # TODO: handle overlap |
| 515 | + self.range_l.sort(key=lambda e: e[0]) |
| 516 | + |
| 517 | + # Now, collapse overlaps |
| 518 | + i=0 |
| 519 | + while i < len(self.range_l): |
| 520 | + if i+1 < len(self.range_l) and self.range_l[i][1]+1 >= self.range_l[i][0]: |
| 521 | + self.range_l[i][1] = self.range_l[i+1][1] |
| 522 | + self.range_l.pop(i+1) |
| 523 | + else: |
| 524 | + i += 1 |
| 525 | + |
| 526 | + if isinstance(nbins,list): |
| 527 | + if len(nbins) not in (0,1): |
| 528 | + raise Exception("Only 0 or 1 argument can be specified to the nbins argument") |
| 529 | + self.nbins = -1 if len(nbins) == 0 else nbins[0] |
| 530 | + else: |
| 531 | + self.nbins = int(nbins) |
| 532 | + |
| 533 | + if len(args) == 0: |
| 534 | + raise Exception("No bins range specified") |
| 535 | + |
| 536 | + # Capture the declaration location of this bin |
| 537 | + frame = inspect.stack()[1] |
| 538 | + self.srcinfo_decl = SourceInfo(frame.filename, frame.lineno) |
| 539 | + |
| 540 | + def build_cov_model(self, parent, name): |
| 541 | + ret = None |
| 542 | + |
| 543 | + # First, need to determine how many total bins |
| 544 | + # Construct a range model |
| 545 | + if self.nbins == -1: |
| 546 | + # unlimited number of bins |
| 547 | + if len(self.range_l) == 1: |
| 548 | + r = self.range_l[0] |
| 549 | + ret = CoverpointBinArrayModel(name, 0, r[0], r[1]) |
| 550 | + else: |
| 551 | + idx=0 |
| 552 | + ret = CoverpointBinCollectionModel(name) |
| 553 | + for r in self.range_l: |
| 554 | + if len(r) == 2: |
| 555 | + b = ret.add_bin(CoverpointBinArrayModel(name, idx, r[0], r[1])) |
| 556 | + b.srcinfo_decl = self.srcinfo_decl |
| 557 | + idx += ((r[1] - r[0]) + 1) |
| 558 | + elif len(r) == 1: |
| 559 | + b = ret.add_bin(CoverpointBinSingleValModel(name + "[" + str(idx) + "]", r[0])) |
| 560 | + b.srcinfo_decl = self.srcinfo_decl |
| 561 | + idx += 1 |
| 562 | + else: |
| 563 | + raise Exception("Internal error: expect bin to have 1 or 2 elements not " + |
| 564 | + str(len(r)) + " (" + |
| 565 | + name + " " + self.srcinfo_decl.filename + ":" + |
| 566 | + str(self.srcinfo_decl.lineno) + ")") |
| 567 | + else: |
| 568 | + ret = CoverpointBinCollectionModel.mk_collection(name, |
| 569 | + RangelistModel(self.range_l), self.nbins) |
| 570 | + |
| 571 | + ret.srcinfo_decl = self.srcinfo_decl |
| 572 | + |
| 573 | + return ret |
| 574 | + |
440 | 575 | class binsof(object): |
441 | 576 | # TODO: future implementation of the 'binsof' operator |
442 | 577 |
|
|
0 commit comments