Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B-ASIC - Better ASIC Toolbox
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Computer Engineering
B-ASIC - Better ASIC Toolbox
Commits
d3244f31
Commit
d3244f31
authored
1 year ago
by
Oscar Gustafsson
Browse files
Options
Downloads
Patches
Plain Diff
Add port count to Memory
parent
6c6089a5
No related branches found
No related tags found
1 merge request
!349
Add port count to Memory
Pipeline
#96693
passed
1 year ago
Stage: test
Stage: deploy
Changes
3
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
b_asic/architecture.py
+33
-21
33 additions, 21 deletions
b_asic/architecture.py
b_asic/resources.py
+15
-0
15 additions, 0 deletions
b_asic/resources.py
test/test_architecture.py
+5
-1
5 additions, 1 deletion
test/test_architecture.py
with
53 additions
and
22 deletions
b_asic/architecture.py
+
33
−
21
View file @
d3244f31
...
...
@@ -40,7 +40,7 @@ class Resource:
self
.
_output_count
=
-
1
def
__repr__
(
self
):
return
self
.
_
entity_name
return
self
.
entity_name
def
__iter__
(
self
):
return
iter
(
self
.
_collection
)
...
...
@@ -80,7 +80,7 @@ class Resource:
def
_digraph
(
self
)
->
Digraph
:
dg
=
Digraph
(
node_attr
=
{
'
shape
'
:
'
record
'
})
dg
.
node
(
self
.
_
entity_name
,
self
.
_struct_def
())
dg
.
node
(
self
.
entity_name
,
self
.
_struct_def
())
return
dg
@property
...
...
@@ -100,12 +100,18 @@ class Resource:
if
inputs
:
instrs
=
[
f
"
<
{
instr
}
>
{
instr
}
"
for
instr
in
inputs
]
ret
+=
f
"
{{
{
'
|
'
.
join
(
instrs
)
}
}}|
"
ret
+=
f
"
{
self
.
_
entity_name
}
"
ret
+=
f
"
{
self
.
entity_name
}
"
if
outputs
:
outstrs
=
[
f
"
<
{
outstr
}
>
{
outstr
}
"
for
outstr
in
outputs
]
ret
+=
f
"
|{{
{
'
|
'
.
join
(
outstrs
)
}
}}
"
return
ret
@property
def
entity_name
(
self
)
->
str
:
if
self
.
_entity_name
is
None
:
return
"
Undefined entity name
"
return
self
.
_entity_name
class
ProcessingElement
(
Resource
):
"""
...
...
@@ -149,14 +155,6 @@ class ProcessingElement(Resource):
def
processes
(
self
)
->
Set
[
OperatorProcess
]:
return
{
cast
(
OperatorProcess
,
p
)
for
p
in
self
.
_collection
}
def
input_count
(
self
)
->
int
:
"""
Return number of input ports.
"""
raise
NotImplementedError
()
def
output_count
(
self
)
->
int
:
"""
Return number of output ports.
"""
raise
NotImplementedError
()
class
Memory
(
Resource
):
"""
...
...
@@ -170,6 +168,10 @@ class Memory(Resource):
The type of memory.
entity_name : str, optional
Name of memory entity.
read_ports : int, optional
Number of read ports for memory.
write_ports : int, optional
Number of write ports for memory.
"""
def
__init__
(
...
...
@@ -177,6 +179,8 @@ class Memory(Resource):
process_collection
:
ProcessCollection
,
memory_type
:
str
=
"
RAM
"
,
entity_name
:
Optional
[
str
]
=
None
,
read_ports
:
Optional
[
int
]
=
None
,
write_ports
:
Optional
[
int
]
=
None
,
):
super
().
__init__
(
process_collection
=
process_collection
,
entity_name
=
entity_name
)
if
not
all
(
...
...
@@ -191,6 +195,20 @@ class Memory(Resource):
raise
ValueError
(
f
"
memory_type must be
'
RAM
'
or
'
register
'
, not
{
memory_type
!r}
"
)
read_ports_bound
=
self
.
_collection
.
read_ports_bound
()
if
read_ports
is
None
:
self
.
_output_count
=
read_ports_bound
else
:
if
read_ports
<
read_ports_bound
:
raise
ValueError
(
f
"
At least
{
read_ports_bound
}
read ports required
"
)
self
.
_output_count
=
read_ports
write_ports_bound
=
self
.
_collection
.
write_ports_bound
()
if
write_ports
is
None
:
self
.
_input_count
=
write_ports_bound
else
:
if
write_ports
<
write_ports_bound
:
raise
ValueError
(
f
"
At least
{
write_ports_bound
}
write ports required
"
)
self
.
_input_count
=
write_ports
self
.
_memory_type
=
memory_type
def
__iter__
(
self
)
->
Iterator
[
MemoryVariable
]:
...
...
@@ -386,26 +404,20 @@ class Architecture:
def
_digraph
(
self
)
->
Digraph
:
dg
=
Digraph
(
node_attr
=
{
'
shape
'
:
'
record
'
})
for
i
,
mem
in
enumerate
(
self
.
_memories
):
if
mem
.
_entity_name
is
not
None
:
dg
.
node
(
mem
.
_entity_name
,
mem
.
_struct_def
())
else
:
dg
.
node
(
f
"
MEM-
{
i
}
"
,
mem
.
_struct_def
())
dg
.
node
(
mem
.
entity_name
,
mem
.
_struct_def
())
for
i
,
pe
in
enumerate
(
self
.
_processing_elements
):
if
pe
.
_entity_name
is
not
None
:
dg
.
node
(
pe
.
_entity_name
,
pe
.
_struct_def
())
else
:
dg
.
node
(
f
"
PE-
{
i
}
"
,
pe
.
_struct_def
())
dg
.
node
(
pe
.
entity_name
,
pe
.
_struct_def
())
for
pe
in
self
.
_processing_elements
:
inputs
,
outputs
=
self
.
get_interconnects_for_pe
(
pe
)
for
i
,
inp
in
enumerate
(
inputs
):
for
source
,
cnt
in
inp
.
items
():
dg
.
edge
(
source
.
_
entity_name
,
f
"
{
pe
.
_
entity_name
}
:in
{
i
}
"
,
label
=
f
"
{
cnt
}
"
source
.
entity_name
,
f
"
{
pe
.
entity_name
}
:in
{
i
}
"
,
label
=
f
"
{
cnt
}
"
)
for
o
,
outp
in
enumerate
(
outputs
):
for
dest
,
cnt
in
outp
.
items
():
dg
.
edge
(
f
"
{
pe
.
_
entity_name
}
:out
{
o
}
"
,
dest
.
_
entity_name
,
label
=
f
"
{
cnt
}
"
f
"
{
pe
.
entity_name
}
:out
{
o
}
"
,
dest
.
entity_name
,
label
=
f
"
{
cnt
}
"
)
return
dg
...
...
This diff is collapsed.
Click to expand it.
b_asic/resources.py
+
15
−
0
View file @
d3244f31
import
io
import
re
from
collections
import
Counter
from
functools
import
reduce
from
typing
import
Dict
,
Iterable
,
List
,
Optional
,
Set
,
Tuple
,
TypeVar
,
Union
...
...
@@ -1266,3 +1267,17 @@ class ProcessCollection:
self
.
_schedule_time
,
self
.
_cyclic
,
)
def
read_ports_bound
(
self
)
->
int
:
reads
=
[]
for
process
in
self
.
_collection
:
reads
.
extend
(
set
(
read_time
%
self
.
schedule_time
for
read_time
in
process
.
read_times
)
)
count
=
Counter
(
reads
)
return
max
(
count
.
values
())
def
write_ports_bound
(
self
)
->
int
:
writes
=
[
process
.
start_time
for
process
in
self
.
_collection
]
count
=
Counter
(
writes
)
return
max
(
count
.
values
())
This diff is collapsed.
Click to expand it.
test/test_architecture.py
+
5
−
1
View file @
d3244f31
...
...
@@ -103,9 +103,13 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule):
Memory
(
pc
)
for
pc
in
mvs
.
split_on_ports
(
read_ports
=
1
,
write_ports
=
1
)
]
assert
len
(
memories
)
==
1
for
i
,
memory
in
enumerate
(
memories
):
memory
.
set_entity_name
(
f
"
MEM
{
i
}
"
)
s
=
'
digraph {
\n\t
node [shape=record]
\n\t
MEM0 [label=MEM0]
\n
}
'
s
=
(
'
digraph {
\n\t
node [shape=record]
\n\t
MEM0 [label=
"
{<in0> in0}|MEM0|{<out0>
'
'
out0}
"
]
\n
}
'
)
assert
memory
.
_digraph
().
source
in
(
s
,
s
+
'
\n
'
)
# Create architecture from
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment