I would like to increase the number of AsIDBits in the Rocket-Chip from zero to eight and was wondering how that could be accomplished.
tile/BaseTile.Scala
trait HasNonDiplomaticTileParameters {
implicit val p: Parameters
//...
def asIdBits: Int = p(ASIdBits)
//...
}
https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala
I would like to implement a class like similar to those defined here
subsystem/Config.Scala
//...
class WithFPUWithoutDivSqrt extends Config((site, here, up) => {
case RocketTilesKey => up(RocketTilesKey, site) map { r =>
r.copy(core = r.core.copy(fpu = r.core.fpu.map(_.copy(divSqrt = false))))
}
})
class WithBootROMFile(bootROMFile: String) extends Config((site, here, up) => {
case BootROMLocated(x) => up(BootROMLocated(x), site).map(_.copy(contentFileName = bootROMFile))
})
class WithSynchronousRocketTiles extends Config((site, here, up) => {
case RocketCrossingKey => up(RocketCrossingKey, site) map { r =>
r.copy(crossingType = SynchronousCrossing())
}
})
//...
https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/subsystem/Configs.scala
I tried doing this
class SetAsIDBits(n: Int) extends Config(
(site, here, up) => {
case ASIdBits => n
}
)
But got an error listed below
Configs.scala:272:10: not found: value ASIdBits
[error] case ASIdBits => n
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
I think this is just indicating that ASIdBits was not defined. You can try importing it:
import freechips.rocketchip.rocket.ASIdBits
Related
I would like for a higher order function to be able to catch the signature parameters of the passed function which can have different signature.
I don't know if it's feasible but this was my approach to it :
type FuncA = (a: string, b: number) => void
type FuncB = (a: string) => void
type Func = FuncA | FuncB
const a: FuncA = (a: string, b: number) => {
console.log('FuncA')
}
const b: FuncB = (a: string) => {
console.log('FuncB')
}
// My higher order function
const c = (func: Func) => {
// do something here...
return (...args: Parameters<typeof func>) => {
func(...args) // Expected 2 arguments, but got 0 or more. ts(2556). An argument for 'a' was not provided.
}
}
My higher order function c couldn't pass the parameters of func
It seems like TypeScript cannot discriminate the different possible signature of type Func.
Does anyone know a pattern to write this kind of code?
Thank you !
This is a tough one because for a function to extend another function doesn't mean quite what you think.
We want the function created by c to require that arguments correspond to the function that it was given. So we use a generic to describe the function.
const c = <F extends Func>(func: F) => {
return (...args: Parameters<F>) => {
func(...args); // still has error
}
}
At this point we still have that error, but when we call c, we get a function which has the right arguments based on whether we gave it a or b.
const cA = c(a); // type: (a: string, b: number) => void
cA("", 0);
const cB = c(b); // type: (a: string) => void
cB("");
As for the error, it has to do with what it means for a function to extend another function. Try changing F extends Func to F extends FuncA and F extends FuncB to see what happens. With F extends FuncB we get an error on c(a), but with F extends FuncA we don't get an error on c(b). Huh?
If you think about it in terms of a callback it makes sense. It's ok to pass a function that requires less arguments than expected, but not ok to pass one that requires more. But we are the ones implementing the callback so this creates a problem for us. If we extend type Func with a function that has no arguments, the empty array from Parameters<F> isn't sufficient to call either type.
We have to make our generic depend on the arguments instead.
type AP = Parameters<FuncA> // type: [a: string, b: number]
type BP = Parameters<FuncB> // type: [a: string]
type Args = AP | BP;
const c = <A extends Args>(func: (...args: A) => void) => {
return (...args: A) => {
func(...args) // no error
}
}
Typescript Playground Link
If you're ok with the decorated function being any function, you could do:
const c = <T extends (...a: any) => any>(func: T) => {
// do something here...
return (...args: Parameters<typeof func>): ReturnType<T> => {
return func(...args);
}
}
Calling it would look like
c<typeof a>(a)('a', 2)
I have two classes that simulate a simple sum operation.
import SumProcessor from "./SumProcessor";
class Calculator {
constructor(private _processor: SumProcessor) { }
sum(a: number, b: number): number {
return this._processor.sum(a, b)
}
}
export default Calculator
And the operation processor.
class SumProcessor {
sum(a: number, b: number): number {
return a + b
}
static log() {
console.log('houston...')
}
}
export default SumProcessor
I'm tryng to mock the class SumProcessor to write the following unit test using jest+ts-jest.
import Calculator from "./Calculator"
import SumProcessor from "./SumProcessor"
import { mocked } from "ts-jest/utils"
jest.mock('./SumProcessor')
describe('Calculator', () => {
it('test sum', () => {
const SomadorMock = <jest.Mock>(SumProcessor)
SomadorMock.mockImplementation(() => {
return {
sum: () => 2
}
})
const somador = new SomadorMock()
const calc = new Calculator(somador)
expect(calc.sum(1, 1)).toBe(2)
})
})
When the static method is present in class SumProcessor, the mock code const SomadorMock = (SumProcessor) indicates the following compilation error:
TS2345: Argument of type '() => jest.Mock<any, any>' is not assignable to parameter of type '(values?: object, option
s?: BuildOptions) => SumOperator'.
Type 'Mock<any, any>' is missing the following properties from type 'SumOperator...
If the static method is removed from SumProcessor class, everything work's fine.
Can anybody help?
since you have already mocked the SumProcessor class with jest.mock('./SumProcessor'); you can just add a spy to the method you would like to mock, for an example:
jest.spyOn(SumProcessor.prototype, 'sum').mockImplementation(() => 2);
this way your test class would look something like this:
import Calculator from "./Calculator"
import SumProcessor from "./SumProcessor"
jest.mock('./SumProcessor')
describe('Calculator', () => {
it('test sum', () => {
jest.spyOn(SumProcessor.prototype, 'sum').mockImplementation(() => 2);
const somador = new SumProcessor();
const calc = new Calculator(somador)
expect(calc.sum(1, 1)).toBe(2)
})
})
much simpler, right?
I am using the following approach to memoize a TypeScript getter using a decorator but wanted to know if there is a better way. I am using the popular memoizee package from npm as follows:
import { memoize } from '#app/decorators/memoize'
export class MyComponent {
#memoize()
private static memoizeEyeSrc(clickCount, maxEyeClickCount, botEyesDir) {
return clickCount < maxEyeClickCount ? botEyesDir + '/bot-eye-tiny.png' : botEyesDir + '/bot-eye-black-tiny.png'
}
get leftEyeSrc() {
return MyComponent.memoizeEyeSrc(this.eyes.left.clickCount, this.maxEyeClickCount, this.botEyesDir)
}
}
AND the memoize decorator is:
// decorated method must be pure
import * as memoizee from 'memoizee'
export const memoize = (): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const func = descriptor.value
descriptor.value = memoizee(func)
return descriptor
}
}
Is there a way to do this without using two separate functions in MyComponent and to add the decorator directly to the TypeScript getter instead?
One consideration here is that the decorated function must be pure (in this scenario) but feel free to ignore that if you have an answer that doesn't satisfy this as I have a general interest in how to approach this problem.
The decorator can be extended to support both prototype methods and getters:
export const memoize = (): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
if ('value' in descriptor) {
const func = descriptor.value;
descriptor.value = memoizee(func);
} else if ('get' in descriptor) {
const func = descriptor.get;
descriptor.get = memoizee(func);
}
return descriptor;
}
}
And be used directly on a getter:
#memoize()
get leftEyeSrc() {
...
}
Based on #estus answer, this is what I finally came up with:
#memoize(['this.eyes.left.clickCount'])
get leftEyeSrc() {
return this.eyes.left.clickCount < this.maxEyeClickCount ? this.botEyesDir + '/bot-eye-tiny.png' : this.botEyesDir + '/bot-eye-black-tiny.png'
}
And the memoize decorator is:
// decorated method must be pure when not applied to a getter
import { get } from 'lodash'
import * as memoizee from 'memoizee'
// noinspection JSUnusedGlobalSymbols
const options = {
normalizer(args) {
return args[0]
}
}
const memoizedFuncs = {}
export const memoize = (props: string[] = []): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
props = props.map(prop => prop.replace(/^this\./, ''))
if ('value' in descriptor) {
const valueFunc = descriptor.value
descriptor.value = memoizee(valueFunc)
} else if ('get' in descriptor) {
const getFunc = descriptor.get
// args is used here solely for determining the memoize cache - see the options object
memoizedFuncs[propertyKey] = memoizee((args: string[], that) => {
const func = getFunc.bind(that)
return func()
}, options)
descriptor.get = function() {
const args: string[] = props.map(prop => get(this, prop))
return memoizedFuncs[propertyKey](args, this)
}
}
return descriptor
}
}
This allows for an array of strings to be passed in which determine which properties will be used for the memoize cache (in this case only 1 prop - clickCount - is variable, the other 2 are constant).
The memoizee options state that only the first array arg to memoizee((args: string[], that) => {...}) is to be used for memoization purposes.
Still trying to get my head around how beautiful this code is! Must have been having a good day. Thanks to Yeshua my friend and Saviour :)
I have a function retry which basically looks like this (simplified):
object SomeObject {
def retry[T](n: Int)(fn: => T): Option[T] = {
val res = try {
Some(fn)
} catch {
case _: Exception => None
}
res match {
case Some(x) => Some(x)
case None =>
if (n > 1)
//make it sleep for a little while
retry(n - 1)(fn)
else None
}
}
}
I need to make some pause between the attempts. As I was told, it's not acceptable to call Thread.sleep(123) inside an actor:
class MyActor extends Actor {
//......
def someFunc = {
Thread.sleep(456) // it's not acceptable in an actor, there is another way to do it
}
}
Obviously, I don't know whether or not a client will use SomeObject.retry inside an actor:
class MyActor extends Actor {
//......
def someFunc = {
SomeObject.retry(5)(someRequestToServer) // ops, SomeObject.retry uses Thread.sleep!
}
}
So if I just add:
res match {
case Some(x) => Some(x)
case None =>
if (n > 1)
//make it sleep for a little while
Thread.sleep(123) // ops, what if it's being called inside an actor by a client?!
retry(n - 1)(fn)
else None
}
}
it won't be sensible, will it? If not, what do I do?
Yes, calling Thread.sleep is a bad idea as in an actor system threads are normally a limited resource shared between Actors. You do not want an Actor calling sleep and hogging a Thread from other Actors.
What you should do instead is use the Scheduler (see docs) to have your actor sent a message to itself sometime in the future to retry. To do this, you would have to move the retry code out of SomeObject and into the Actor
class MyActor extends Actor {
import context.system.dispatcher
def receive = {
case DoIt(retries) if retries > 0 =>
SomeObject.attempt(someRequestToServer) match {
case Some(x) => ...
case None =>
context.system.scheduler.scheduleOnce(5.seconds, self, DoIt(retries - 1))
}
}
}
Then if you were using SomeObject.try outside of an Actor System
def attempt(retries: Int) = {
SomeObject.attempt(someRequestToServer) match {
case Some(x) => ...
case None if retries > 0 => {
Thread.sleep(123)
attempt(retries - 1)
}
}
}
Where SomeObject.attempt is:
object SomeObject {
def attempt[T](fn: => T): Option[T] =
try {
Some(fn)
} catch {
case _: Exception => None
}
}
I am trying connecting to my model class defined in /application/models named user.php.
Following is how my Bootstrap looks like:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
protected function _initAppAutoload() {
$autoloader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH,
'resourceTypes' => array(
'model' => array(
'path' => 'models',
'namespace' => 'Model',
)
)
));
echo '<pre>';
var_dump($autoloader);
return $autoloader;
}
}
Folling is my application.ini
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
Following is my IndexController.php
class IndexController extends Zend_Controller_Action {
private $user_connection;
private $login_status;
public function init() {
/* Initialize action controller here */
$this->user_connection = new Application_Model_User();
}
public function indexAction() {
$sql = " SELECT *
FROM USER";
$this->view->deals = $this->user_connection->select($sql);
}
following is my user.php file:
class Application_Model_User extends Application_Model_Db_Connection {
public function __construct() {
parent::__construct();
}
public function Connection(){
return $this->getConnection();
}
public function insert($data, $table = 'user'){
return parent::insert($table, $data);
}
public function select($sql){
return parent::select($sql);
}
}
Strange part is, I am developing on windows and everything runs fine, but when I push the same code to my ec2 linux instance, I get this fatal error.
Fatal error: Class 'Application_Model_User' not found in /var/www/html/dev/application/controllers/IndexController.php on line 11
I went through many questions on stack overflow and tried most of them, but I am not close to solve this problem. Any help would be appreciated.
I was able to fix the above issue, it was due to case sensitivity of linux. I renamed my models with first letter capital and was able to access them in my Controller.
user.php -> User.php
also for adding subfolder to your model you can add following to the bootstrap.
protected function _initAppAutoload() {
$autoloader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH,
'resourceTypes' => array(
'model' => array(
'path' => 'models/',
'namespace' => 'Model_',
),
'model_db' => array(
'path' => 'models/db',
'namespace' => 'Model_Db_'
)
)
));