Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tima
sls
projects
QECE
Commits
e2440b54
Commit
e2440b54
authored
Jan 11, 2022
by
Bruno Ferres
Browse files
Merge branch 'v1.1.0' into 'master'
v1.1.0: new way to configure and import QECE in external projects See merge request
!1
parents
4e8cec41
b9ec569a
Changes
131
Hide whitespace changes
Inline
Side-by-side
build.sbt
View file @
e2440b54
// See README.md for license details.
ThisBuild
/
scalaVersion
:=
"2.12.12"
ThisBuild
/
version
:=
"1.
0
.0"
ThisBuild
/
version
:=
"1.
1
.0"
ThisBuild
/
organization
:=
"fr.tima"
parallelExecution
in
Test
:=
true
...
...
@@ -54,12 +54,6 @@ addCommandAlias("lintCheck", "; scalastyle; test:scalastyle" +
"; scalafmtCheck; test:scalafmtCheck"
+
"; scalafix --check; test:scalafix --check"
)
/* ---- Stack overflow exception occurs when doc is generated ---- */
addCommandAlias
(
"disableDocGeneration"
,
"set publishArtifact in(Compile, packageDoc) := false"
)
addCommandAlias
(
"enableDocGeneration"
,
"set publishArtifact in(Compile, packageDoc) := true"
)
addCommandAlias
(
"quickPublish"
,
"disableDocGeneration; publishLocal; enableDocGeneration"
)
addCommandAlias
(
"disableParallel"
,
"set parallelExecution in Test := false;"
)
addCommandAlias
(
"enableParallel"
,
"set parallelExecution in Test := true;"
)
...
...
src/main/scala/CustomLogging.scala
View file @
e2440b54
...
...
@@ -19,38 +19,38 @@ package qece
import
logger.
{
LazyLogging
,
Logger
}
trait
CustomLogging
extends
LazyLogging
{
Logger
.
setLevel
(
this
.
getClass
,
Proj
ec
t
Con
fig
.
logLevel
)
Logger
.
setLevel
(
this
.
getClass
,
Q
ec
e
Con
text
.
logger
.
logLevel
)
def
mylog
(
str
:
String
)
=
{
Proj
ec
t
Con
fig
.
enableLog
match
{
protected
def
mylog
(
str
:
String
)
=
{
Q
ec
e
Con
text
.
logger
.
enableLog
match
{
case
true
=>
logger
.
warn
(
s
"[${Utils.getTime}] $str"
)
case
false
=>
}
}
def
mytrace
(
str
:
String
)
=
{
Proj
ec
t
Con
fig
.
enableTrace
match
{
protected
def
mytrace
(
str
:
String
)
=
{
Q
ec
e
Con
text
.
logger
.
enableTrace
match
{
case
true
=>
logger
.
warn
(
s
"[${Utils.getTime}]"
+
" "
*
8
+
s
"$str"
)
case
false
=>
}
}
def
mydebug
(
str
:
String
)
=
{
Proj
ec
t
Con
fig
.
enableDebug
match
{
protected
def
mydebug
(
str
:
String
)
=
{
Q
ec
e
Con
text
.
logger
.
enableDebug
match
{
case
true
=>
logger
.
warn
(
s
"[DEBUG][${Utils.getTime}] $str"
)
case
false
=>
}
}
def
mysyncdebug
(
str
:
String
)
=
{
Proj
ec
t
Con
fig
.
enableSyncDebug
match
{
protected
def
mysyncdebug
(
str
:
String
)
=
{
Q
ec
e
Con
text
.
logger
.
enableSyncDebug
match
{
case
true
=>
logger
.
warn
(
s
"[SYNCHRO][${Utils.getTime}] $str"
)
case
false
=>
}
}
def
timeError
(
str
:
String
)
=
{
Proj
ec
t
Con
fig
.
enableError
match
{
protected
def
timeError
(
str
:
String
)
=
{
Q
ec
e
Con
text
.
logger
.
enableError
match
{
case
true
=>
logger
.
error
(
s
"[${Utils.getTime}] $str"
)
case
false
=>
}
...
...
src/main/scala/ProjectConfig.scala
deleted
100644 → 0
View file @
4e8cec41
/** Part of QECE (Quick Exploration using Chisel Estimators) program. Copyright (C) <2021> <Bruno FERRES>
*
* This program is developped at TIMA, Grenoble. Please contact Bruno FERRES (bruno.ferres@grenoble-inp.org) or Olivier
* MULLER (olivier.muller@univ-grenoble-alpes.fr) for more informations.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
package
qece
import
logger.LogLevel
import
qece.estimation.macros.MacroBlock
import
qece.estimation.macros.components._
/** Config object for the project. */
object
ProjectConfig
{
// val config = ConfigFactory.load()
/** Define how parallelisation is supposed to be managed */
val
useScalaParSeq
=
false
val
activeWaiting
:
Option
[
Int
]
=
None
//Some(60000)
/** Define default target for the estimators. */
val
defaultBoard
=
"Zedboard"
/** Define synthesis timeout, using the `timeout format`. */
val
synthTimeout
=
"2h"
/** Define the number of threads to be used in the different processes. */
val
numThread
=
4
/** Define used vivado version */
val
vivadoVersion
=
"2017.3"
/** Define number of threads used in each backend call. Put to 1 as syntheses are difficult to parallelize. */
val
backendThreadNumber
=
"1"
/** Define number of thread used for simulation */
val
simulationThreadNumber
=
16
/** Define which backend to use in simulation based estimators */
val
simulationBackend
=
"treadle"
/** Define number of thread used for synthesis */
val
synthesisThreadNumber
=
1
/** Define target period for synthesis, in ns */
val
period
=
10
/** ============ Macro configurations ================= */
// TODO: manage default here
// val defaultMacroSeq = MacroSeq(List(MacUnit, MemoryBlock))
/** MacUnit config. */
/** max absorbed registers. */
val
maxDspRegister
=
3
/** Memory block register. */
/** max address amount, as a power of two */
val
maxMemoryBlockAddr
=
16
/** Mux config. */
/** maximum number of input for a mux block, as a power of two */
val
maxMuxBlockInput
=
8
/** ============== Characterization =================== */
/** Specify the bitwidths to use for characterization. This may use expert knowledge about the target, to cope with
* transfert effect on the technology.
*/
val
characterizationBitMap
=
Map
[
MacroBlock
[
_
]
,
List
[
Int
]](
MemoryBlock
->
List
(
1
,
8
,
32
,
64
,
128
,
256
,
512
,
1024
))
.
withDefaultValue
(
List
(
1
,
2
,
4
,
8
,
15
,
16
,
32
,
64
,
128
,
256
))
val
characterizeRegisters
=
true
/** Basic bitwidth to run characterization on. */
val
baseWidth
=
1
/** ============== Loggers =================== */
/** Define custom log level. */
//TODO: proper way to handle this
val
logLevel
=
LogLevel
.
Warn
val
enableTrace
=
true
val
enableLog
=
true
val
enableError
=
true
val
enableDebug
=
false
val
enableSyncDebug
=
false
/** Define chisel log level. */
val
chiselLogLevel
=
LogLevel
.
None
/** Stack tace depth */
val
stackDepth
=
0
/** ============== Estimation =================== */
/** Enable or not invalid estimation. */
val
enableInvalidEstimation
=
true
/** ============== Generation =================== */
/** Default default generation directory for emitted files. */
val
genDirectory
=
"chisel_gen/"
/** Define csv separator. */
val
csvSeparator
=
";"
/** Force synthesis disable for debug purposes. */
val
disableSynthesis
=
false
/** Force implementation disable for debug purposes. */
val
disableImplementation
=
false
/** ========== Exploration configurations =============== */
val
defaultCost
=
0.0
/** ========== Transform configurations =============== */
// TODO: manage default here
// lazy val defaultTransformSeq = TransformSeq.resources
/** ========== Timeouts configuration =============== */
// define timeout for the different transforms
val
totalEstimationTimeout
=
"4h"
val
replaceMacroTimeout
=
"30min"
val
primitiveReportTimeout
=
"30min"
val
estimateResourceTimeout
=
"Inf"
val
endpointReportTimeout
=
"2h"
val
criticalPathTimeout
=
"Inf"
// useless as timeout already done at backend level
val
synthesisTransformTimeout
=
"Inf"
}
src/main/scala/QeceContext.scala
0 → 100644
View file @
e2440b54
/** Part of QECE (Quick Exploration using Chisel Estimators) program. Copyright (C) <2021> <Bruno FERRES>
*
* This program is developped at TIMA, Grenoble. Please contact Bruno FERRES (bruno.ferres@grenoble-inp.org) or Olivier
* MULLER (olivier.muller@univ-grenoble-alpes.fr) for more informations.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
package
qece
import
logger.LogLevel
import
qece.estimation.macros.MacroBlock
import
qece.estimation.macros.components._
import
scala.util.DynamicVariable
/** Configuration of the QECE core, i.e. estimation and exploration features.
*
* @todo manage the default transforms here
* @param enableInvalidEstimation
* either fail on invalid estimation, or just continue and mark as failure
* @param defaultCost
* default cost for estimated metrics (e.g. on estimation failure)
*/
case
class
CoreConfig
(
enableInvalidEstimation
:
Boolean
=
true
,
defaultCost
:
Double
=
0.0
)
/** Configuration of the parallelism management.
*
* @param useScalaParSeq
* either use scala built-in ParSeq (which resulted in starving threads) or custom ThreadPool
* @param activeWaiting
* if useScalaParSeq == false, define the ThreadPool behavior, either using event driven waiting, or active waiting
* @param numThread
* define the number of threads to be used in the different processes (can be overrided by more specific parameters)
*/
case
class
ParallelConfig
(
useScalaParSeq
:
Boolean
=
false
,
activeWaiting
:
Option
[
Int
]
=
None
,
numThread
:
Int
=
4
)
/** Configuration of the FPGA backend.
*
* @param targetBoard
* define the name of the target board, with respect to the ones defined in the backend package
* @param vivadoVersion
* define the vivado version to be used for synthesis
* @param backendThreadNumber
* define the number of threads used in each FPGA backend call.
* set to 1 as syntheses are difficult to parallelize efficiently
* @param period
* define the target period for FPGA backend calls (in ns)
*/
case
class
BackendConfig
(
targetBoard
:
String
=
"Zedboard"
,
vivadoVersion
:
String
=
"2017.3"
,
backendThreadNumber
:
String
=
"1"
,
targetPeriod
:
Int
=
10
)
/** Configuration of the simulation backend.
*
* @param simulationBackend
* define which backend to be used for simulations
*/
case
class
SimulationConfig
(
backend
:
String
=
"treadle"
)
/** Configuration of the characterization system, including the macro block mechanism.
*
* @todo manage defaultMacroSeq configuration here ?
* @param maxDspRegister
* max. amount of registers that can be absorbed in a MacUnit pattern
* @param maxMemoryBlockAddr
* max. number of addresses available on MemoryBlock (as a power of two)
* @param maxMuxBlockInput
* max. number of inputs for a MuxBlock (as a power of two)
* @param characterizationBitMap
* specify the bitwidths to use for characterization. This may use expert knowledge about the target, to cope with
* transfert effects on the technology.
* @param characterizeRegisters
* either use backend to characterize the registers, or use naive estimation through primitive counting
* @param baseWidth
* base bitwidth to run characterization on
*/
case
class
CharacterizationConfig
(
maxDspRegister
:
Int
=
3
,
maxMemoryBlockAddr
:
Int
=
16
,
maxMuxBlockInput
:
Int
=
8
,
characterizationBitMap
:
Map
[
MacroBlock
[
_
]
,
List
[
Int
]]
=
Map
[
MacroBlock
[
_
]
,
List
[
Int
]](
MemoryBlock
->
List
(
1
,
8
,
32
,
64
,
128
,
256
,
512
,
1024
))
.
withDefaultValue
(
List
(
1
,
2
,
4
,
8
,
15
,
16
,
32
,
64
,
128
,
256
)),
characterizeRegisters
:
Boolean
=
true
,
baseWidth
:
Int
=
1
)
/** Configuration of the logging system.
*
* @param logLevel
* global logging level
* @param enableTrace
* @param enableLog
* @param enableError
* @param enableDebug
* @param enableSyncDebug
* @param chiselLogLevel
* define chisel logging level
* @param stackDepth
* define the size of the stack trace to be displayed on exception handling
*/
case
class
LoggerConfig
(
logLevel
:
LogLevel.Value
=
LogLevel
.
Warn
,
enableTrace
:
Boolean
=
true
,
enableLog
:
Boolean
=
true
,
enableError
:
Boolean
=
true
,
enableDebug
:
Boolean
=
false
,
enableSyncDebug
:
Boolean
=
false
,
chiselLogLevel
:
LogLevel.Value
=
LogLevel
.
None
,
stackDepth
:
Int
=
0
)
/** Configuration of the emission system.
*
* @param genDirectory
* default generation directory for the emitted files
* @param csvSeparator
* define the csv separator used for result files
* @param disableSynthesis
* force synthesis disable (for debug purposes)
* @param disableImplementation
* force implementation (P&R) disable (for debug purposes)
*/
case
class
EmissionConfig
(
basePath
:
String
=
"chisel_gen/"
,
targetPath
:
String
=
"default/"
,
csvSeparator
:
String
=
";"
,
disableSynthesis
:
Boolean
=
false
,
disableImplementation
:
Boolean
=
false
)
/** Various timeouts configuration
*
* @param totalEstimation
* timeout for a whole estimation process
* @param replaceMacro
* timeout for the replace macro transform
* @param primitiveReport
* timeout for the primitive report transform
* @param estimateResource
* timeout for the estimate resource transform
* @param endpointReport
* timeout for the endpoint report transform
* @param criticalPath
* timeout for the critical path estimation transform
* @param synthesis
* define synthesis timeout, using the `timeout format`
* @param synthesisTransform
* useless as the timeout is already defined at backend level
*/
case
class
TimeoutConfig
(
totalEstimation
:
String
=
"4h"
,
replaceMacro
:
String
=
"30min"
,
primitiveReport
:
String
=
"30min"
,
estimateResource
:
String
=
"Inf"
,
endpointReport
:
String
=
"2h"
,
criticalPath
:
String
=
"Inf"
,
synthesis
:
String
=
"2h"
,
synthesisTransform
:
String
=
"Inf"
)
/** Global configuration for the project.
*
* @param core
* QECE core configuration, i.e. estimation and exploration features
* @param parallel
* thread management configuration
* @param backend
* FPGA backend configuration
* @param simulation
* simulation backend configuration
* @param characterization
* characterization system configuration
* @param logger
* logging system configuration
* @param emission
* emission system configuration
* @param timeout
* timeout system configuration
*/
case
class
QeceConfig
(
core
:
CoreConfig
=
CoreConfig
(),
parallel
:
ParallelConfig
=
ParallelConfig
(),
backend
:
BackendConfig
=
BackendConfig
(),
simulation
:
SimulationConfig
=
SimulationConfig
(),
characterization
:
CharacterizationConfig
=
CharacterizationConfig
(),
logger
:
LoggerConfig
=
LoggerConfig
(),
emission
:
EmissionConfig
=
EmissionConfig
(),
timeout
:
TimeoutConfig
=
TimeoutConfig
()
)
{
/** Create a copy of this by update members.
*
* @param core
* function to update the core config
* @param parallel
* function to update the parallel config
* @param backend
* function to update the backend config
* @param simulation
* function to update the simulation config
* @param characterization
* function to update the characterization config
* @param logger
* function to update the logger config
* @param emission
* function to update the emission config
* @param timeout
* function to update the timeout config
*/
def
funcCopy
(
core
:
CoreConfig
=>
CoreConfig
=
(
m
=>
m
),
parallel
:
ParallelConfig
=>
ParallelConfig
=
(
m
=>
m
),
backend
:
BackendConfig
=>
BackendConfig
=
(
m
=>
m
),
simulation
:
SimulationConfig
=>
SimulationConfig
=
(
m
=>
m
),
characterization
:
CharacterizationConfig
=>
CharacterizationConfig
=
(
m
=>
m
),
logger
:
LoggerConfig
=>
LoggerConfig
=
(
m
=>
m
),
emission
:
EmissionConfig
=>
EmissionConfig
=
(
m
=>
m
),
timeout
:
TimeoutConfig
=>
TimeoutConfig
=
(
m
=>
m
)
)
:
QeceConfig
=
this
.
copy
(
core
=
core
(
this
.
core
),
parallel
=
parallel
(
this
.
parallel
),
backend
=
backend
(
this
.
backend
),
simulation
=
simulation
(
this
.
simulation
),
characterization
=
characterization
(
this
.
characterization
),
logger
=
logger
(
this
.
logger
),
emission
=
emission
(
this
.
emission
),
timeout
=
timeout
(
this
.
timeout
)
)
}
/** A global object used to build the global configuration of the project.
*
* A DynamicVariable is used to allow overriding of the basic configuration, as well as some syntactic sugar
* to allow users to do it in a concise way.
*/
object
QeceContext
extends
DynamicVariable
(
QeceConfig
()){
def
core
=
value
.
core
def
parallel
=
value
.
parallel
def
backend
=
value
.
backend
def
simulation
=
value
.
simulation
def
characterization
=
value
.
characterization
def
logger
=
value
.
logger
def
emission
=
value
.
emission
def
timeout
=
value
.
timeout
/** Run a block of code in a context where the context is updated.
*
* @param core
* function to update the core config
* @param parallel
* function to update the parallel config
* @param backend
* function to update the backend config
* @param simulation
* function to update the simulation config
* @param characterization
* function to update the characterization config
* @param logger
* function to update the logger config
* @param emission
* function to update the emission config
* @param timeout
* function to update the timeout config
*/
def
withValue
[
S
](
core
:
CoreConfig
=>
CoreConfig
=
(
m
=>
m
),
parallel
:
ParallelConfig
=>
ParallelConfig
=
(
m
=>
m
),
backend
:
BackendConfig
=>
BackendConfig
=
(
m
=>
m
),
simulation
:
SimulationConfig
=>
SimulationConfig
=
(
m
=>
m
),
characterization
:
CharacterizationConfig
=>
CharacterizationConfig
=
(
m
=>
m
),
logger
:
LoggerConfig
=>
LoggerConfig
=
(
m
=>
m
),
emission
:
EmissionConfig
=>
EmissionConfig
=
(
m
=>
m
),
timeout
:
TimeoutConfig
=>
TimeoutConfig
=
(
m
=>
m
)
)(
thunk
:
=>
S
)
:
S
=
withValue
(
this
.
copy
(
core
=
core
,
parallel
=
parallel
,
backend
=
backend
,
simulation
=
simulation
,
characterization
=
characterization
,
logger
=
logger
,
emission
=
emission
,
timeout
=
timeout
)
)(
thunk
)
/** Create a copy of the current configuration, and potentially update it.
*
* @param core
* function to update the core config
* @param parallel
* function to update the parallel config
* @param backend
* function to update the backend config
* @param simulation
* function to update the simulation config
* @param characterization
* function to update the characterization config
* @param logger
* function to update the logger config
* @param emission
* function to update the emission config
* @param timeout
* function to update the timeout config
*/
def
copy
(
core
:
CoreConfig
=>
CoreConfig
=
(
m
=>
m
),
parallel
:
ParallelConfig
=>
ParallelConfig
=
(
m
=>
m
),
backend
:
BackendConfig
=>
BackendConfig
=
(
m
=>
m
),
simulation
:
SimulationConfig
=>
SimulationConfig
=
(
m
=>
m
),
characterization
:
CharacterizationConfig
=>
CharacterizationConfig
=
(
m
=>
m
),
logger
:
LoggerConfig
=>
LoggerConfig
=
(
m
=>
m
),
emission
:
EmissionConfig
=>
EmissionConfig
=
(
m
=>
m
),
timeout
:
TimeoutConfig
=>
TimeoutConfig
=
(
m
=>
m
)
)
:
QeceConfig
=
this
.
value
.
funcCopy
(
core
=
core
,
parallel
=
parallel
,
backend
=
backend
,
simulation
=
simulation
,
characterization
=
characterization
,
logger
=
logger
,
emission
=
emission
,
timeout
=
timeout
)
}
src/main/scala/Utils.scala
View file @
e2440b54
...
...
@@ -18,8 +18,15 @@ package qece
import
java.util.
{
Calendar
,
Date
}
/** Helpers that can be helpful for logging purposes.
*
* @todo maybe it should not be part of the API.
*/
object
Utils
{
/** retrieve the current date as a String. */
def
getDate
:
String
=
new
Date
().
toString
/** retrieve the current date as a Date. */
def
getTime
:
Date
=
Calendar
.
getInstance
().
getTime
()
}
src/main/scala/backend/FPGA.scala
View file @
e2440b54
...
...
@@ -16,7 +16,7 @@
*/
package
qece.backend
import
qece.
{
Utils
,
Proj
ec
t
Con
fig
,
CustomLogging
}
import
qece.
{
Utils
,
Q
ec
e
Con
text
,
CustomLogging
}
import
qece.backend.exceptions._
import
qece.backend.utils._
...
...
@@ -30,17 +30,20 @@ object FPGA {
case
_
=>
throw
UnknownBoardException
(
s
"Did not found board with name $name"
)
}
}
def
default
:
FPGA
=
FPGA
(
Proj
ec
t
Con
fig
.
defaul
tBoard
)
def
default
:
FPGA
=
FPGA
(
Q
ec
e
Con
text
.
backend
.
targe
tBoard
)
}
/** FPGA class for backend access. */
abstract
class
FPGA
extends
CustomLogging
{
/** Name of this particular [[FPGA]]. */
val
name
=
this
.
getClass
.
getSimpleName
val
nbThread
=
ProjectConfig
.
backendThreadNumber
val
timeoutOpt
=
Seq
(
"-s"
,
"SIGKILL"
,
"-k"
,
"1s"
,
ProjectConfig
.
synthTimeout
)
/** Run full synthesis, and report both timing and resources
* @param root
protected
val
nbThread
=
QeceContext
.
backend
.
backendThreadNumber